package query_service

import (
	"github.com/gin-gonic/gin"
	"mine-info-server/app/convertor"
	"mine-info-server/domain/plan-manage-context/command"
	"mine-info-server/domain/plan-manage-context/repo"
	"mine-info-server/domain/plan-manage-context/service"
	"mine-info-server/utils"
	"mine-info-server/utils/redis_mq"
)

/*
   @author：zhongyang
   @date:2023/4/2
   @description: 计划管理-命令应用服务（增删改）
*/

type PlanManageCommandService struct {
	PlanDomainService *service.PlanManageDomainService
	PlanManageRepo    repo.PlanManageIRepo
	planConvertor     convertor.PlanManageConvertor
}

func (p *PlanManageCommandService) CreatePlan(ctx *gin.Context, command *command.PlanCreateCommand) error {
	// todo 这里还需要mysql的事务控制，目前考虑用wire框架
	// 将命令转换为聚合根
	planAggregate, err := p.planConvertor.CreatePlanAggregate(command.Name, command.StartTime, command.EndTime, command.ParentId)
	if err != nil {
		return err
	}
	// 计划实体执行创建计划的业务逻辑
	planAggregate.Create(ctx)
	// 调用仓储层，做持久化操作
	err = p.PlanManageRepo.CreatePlan(ctx, planAggregate)
	if err != nil {
		return err
	}
	// 2.发送领域事件到MQ
	redis_mq.SendPlanExpireDelayMsg(ctx, command.Name, command.EndTime)
	return nil
}

func (p *PlanManageCommandService) DeletePlan(ctx *gin.Context, command *command.PlanDeleteCommand) error {
	// 获取聚合根
	planAggregate, err := p.PlanManageRepo.FindPlanById(ctx, command.PlanId)
	if err != nil {
		return err
	}
	// 这里涉及多实体，考虑放到领域服务完成删除
	err = p.PlanDomainService.DeletePlan(ctx, planAggregate)
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) EditPlan(ctx *gin.Context, command *command.PlanEditCommand) error {
	planAggregate, err := p.PlanManageRepo.FindPlanById(ctx, command.PlanId)
	if err != nil {
		return err
	}
	// 聚合根完成编辑计划的业务逻辑
	err = planAggregate.Edit(command.Name, command.StartTime, command.EndTime, command.ParentId)
	if err != nil {
		return err
	}
	// 调用仓储层完成数据持久化
	err = p.PlanManageRepo.EditPlan(ctx, planAggregate)
	if err != nil {
		return err
	}
	// 发布计划更新事件给MQ

	return nil
}

func (p *PlanManageCommandService) EditTarget(context *gin.Context, editCommand *command.TargetEditCommand) error {
	planAggregate, err := p.PlanManageRepo.FindPlanContainsDetailById(context, editCommand.PlanID)
	if err != nil {
		return err
	}
	// 聚合根实现修改目标的业务逻辑
	err = planAggregate.EditTarget(editCommand.PlanID, editCommand.Target)
	if err != nil {
		return err
	}
	// 持久化操作
	err = p.PlanManageRepo.EditTarget(context, planAggregate)
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) SubmitPlanReport(context *gin.Context, submitCommand *command.PlanReportSubmitCommand) error {
	plan, err := p.PlanManageRepo.FindPlanById(context, submitCommand.PlanId)
	if err != nil {
		return err
	}
	plan.SubmitReport(submitCommand.RealDay, submitCommand.ExpectDay, submitCommand.IsOverTime, submitCommand.TaskTotal)
	// 调用仓储层完成持久化操作
	err = p.PlanManageRepo.SubmitPlanReport(context, plan)
	if err != nil {
		return err
	}
	return p.PlanManageRepo.FinishPlan(plan)
}

func (p *PlanManageCommandService) CreateTask(context *gin.Context, command *command.CreateTaskCommand) error {
	plan, err := p.PlanManageRepo.FindPlanContainsTaskByPlanIdAndDate(context, command.PlanId, command.ExecuteDate)
	if err != nil {
		return err
	}
	// 通过聚合根完成领域业务逻辑
	plan.CreateTask(command.ExecuteDate, command.Content, command.Level)
	// 持久化操作
	err = p.PlanManageRepo.CreateTask(context, plan)
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) DeleteTaskItemById(context *gin.Context, itemCommand *command.DeleteTaskItemCommand) error {
	// 这里后面可能涉及到要保证计划报告的完整性，所以这里可能不能直接进行删除操作
	return p.PlanManageRepo.DeleteTaskItem(context, itemCommand.TaskItemId)
}

func (p *PlanManageCommandService) DeleteTaskById(context *gin.Context, deleteTaskCommand *command.DeleteTaskCommand) error {
	return p.PlanManageRepo.DeleteTask(context, deleteTaskCommand.TaskId)
}

func (p *PlanManageCommandService) EditTaskItemById(context *gin.Context, editTaskItemCommand *command.EditTaskItemCommand) error {
	return p.PlanDomainService.EditTaskItem(context, editTaskItemCommand.PlanId, editTaskItemCommand.ID, editTaskItemCommand.Level, editTaskItemCommand.Content, editTaskItemCommand.ExecuteDate)
}

func (p *PlanManageCommandService) FinishTaskItem(context *gin.Context, itemCommand *command.FinishTaskItemCommand) error {
	plan, err := p.PlanManageRepo.GetTaskItemById(context, itemCommand.TaskItemId)
	if err != nil {
		return err
	}
	// 完成领域内的业务操作
	err = plan.FinishTaskItem()
	if err != nil {
		return err
	}
	err = p.PlanManageRepo.FinishTaskItem(context, plan)
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) SaveQuestions(context *gin.Context, req *command.SaveQuestionCommand) error {
	plan, err := p.PlanManageRepo.FindOneDayQuestions(context, req.Questions[0].PlanId, req.Questions[0].TaskDate)
	if err != nil {
		return err
	}
	deleteQuestions := plan.DeleteQuestions(req.Questions)
	if len(deleteQuestions) != 0 {
		err := p.PlanManageRepo.BatchDeleteQuestions(deleteQuestions)
		if err != nil {
			return err
		}
	}
	plan.SaveQuestions(req.Questions, utils.GetUserID(context))
	return p.PlanManageRepo.SaveQuestions(plan)
}
